#pragma once

// Copyright (c) 2010 Manuel Peinado Gallego <manuel.peinado@gmail.com>
// Distributed under the MIT license

#include "MaterialPreviewWnd.h"
#include "SelectionManager.h"
#include "Dim.h"
#include "WorldFollower.h"
#include "UiFollower.h"
#include "SmartEnum.h"
class GeometryNode;
class LightNode;
class Shader;
class UniformVar;



class CPropertiesToolBar : public CMFCToolBar {
public:
    virtual void OnUpdateCmdUI(CFrameWnd*, BOOL bDisableIfNoHndler) {
        CMFCToolBar::OnUpdateCmdUI((CFrameWnd*) GetOwner(), bDisableIfNoHndler); }
    virtual BOOL AllowShowOnList() const { return FALSE; }
};


BEGIN_ENUM(PropertyType)
    NOT_INIT=-1, 
    NOTHING, 
    SHAPE, 
    LIGHT, 
    MATERIAL, 
    SHADER_PROGRAM,
    SHADER,
    TEXTURE,
    TEXTURE_LAYER,
    UNIFORM_VAR,
    COUNT
END_ENUM(PropertyType)



class CPropertiesWnd : public CDockablePane, 
                       public WorldFollower, 
                       public UiFollower
{
public:
    CPropertiesWnd();
    virtual ~CPropertiesWnd();


protected:

    void AdjustLayout() override;
    void updateActivePropertyList();

    // -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  
    // Last time the controls were updated. 
    double m_lastUpdateMillis;

    // -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  
    // World/Ui follower overrides
    
    void onUiChanged(Ui* newUi) override;
    void onWorldChanged(World* newWorld) override;
    void onSelectionChanged(SelectionManager* sender) override;
    void onShaderEvent(const ShaderEvent&) override;
    void onNodeEvent(const NodeEvent&) override;
    
    // -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  

    CFont m_fntPropList;
    CComboBox m_wndObjectCombo;
    CPropertiesToolBar m_wndToolBar;
    CMaterialPreviewWnd m_wndMaterialPreview;

    CMFCPropertyGridCtrl m_wndPropList[PropertyTypes::COUNT];
    PropertyType m_activePropertyType;
    CMFCPropertyGridCtrl* activePropList();

    // -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -
    // Stuff related to the "shape" properties list
    
    void createShapePropertyList();
    void updateGeometryPropertyList(const GeometryNode& node);
    void updateGeometryPositionControls(const gx::Mat4& transform);
    void updateGeometryOrientationControls(const gx::Mat4& transform);
    void updateGeometryScaleControls(const gx::Mat4& transform);
    CMFCPropertyGridProperty* m_appearanceTypePGP;
    CMFCPropertyGridProperty* m_appearanceWireframePGP;
    CMFCPropertyGridProperty* m_appearanceFrontMaterialPGP;
    CMFCPropertyGridProperty* m_appearanceBackMaterialPGP;
    CMFCPropertyGridProperty* m_appearanceShaderPGP;
    
    CMFCPropertyGridProperty* m_appearanceScalePGP[3]; // X, Y and Z
    void onScaleProperty(GeometryNode& node, Dim dim);

    CMFCPropertyGridProperty* m_appearanceOrientationPGP[3];
    void onOrientationProperty(GeometryNode& node, Dim dim);

    CMFCPropertyGridProperty* m_appearancePositionPGP[3];
    void onPositionProperty(GeometryNode& node, Dim dim);

    CMFCPropertyGridProperty* m_selectedFacePGP;

    void onShapeProperty(CMFCPropertyGridProperty* pgp);

    // -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -
    // Stuff related to the "light" properties list

    void createLightPropertyList();
    void updateLightPropertyList(const LightNode& node);

    CMFCPropertyGridProperty* m_lightTypePGP;

    CMFCPropertyGridColorProperty* m_lightAmbientColorPGP;
    CMFCPropertyGridColorProperty* m_lightDiffuseColorPGP;
    CMFCPropertyGridColorProperty* m_lightSpecularColorPGP;

    CMFCPropertyGridProperty* m_lightSpotGroup;
    CMFCPropertyGridProperty* m_lightSpotEnablePGP;
    CMFCPropertyGridProperty* m_lightSpotCutoffPGP;

    CMFCPropertyGridProperty* m_lightAttenuationGroup;
    CMFCPropertyGridProperty* m_lightConstantAttenuationPGP;
    CMFCPropertyGridProperty* m_lightLinearAttenuationPGP;
    CMFCPropertyGridProperty* m_lightQuadraticAttenuationPGP;

    void onLightProperty(CMFCPropertyGridProperty* pgp);

    // -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -
    // Stuff related to the "material" properties list

    void createMaterialPropertyList();
    void updateMaterialPropertyList(const Material& mat);

    CMFCPropertyGridProperty* m_materialIdPGP;
    CMFCPropertyGridColorProperty* m_materialAmbientColorPGP;
    CMFCPropertyGridColorProperty* m_materialDiffuseColorPGP;
    CMFCPropertyGridColorProperty* m_materialSpecularColorPGP;
    CMFCPropertyGridProperty* m_materialShininessPGP;
    CMFCPropertyGridProperty* m_materialTransparentPGP;

    void onMaterialProperty(CMFCPropertyGridProperty* pgp);    

    // -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -
    // Stuff related to the "shader program" properties list

    void createShaderProgramPropertyList();
    void updateShaderProgramPropertyList(const ShaderProgram& mat);

    CMFCPropertyGridProperty* m_shaderProgramIdPGP;
    CMFCPropertyGridProperty* m_shaderProgramLinksPGP;

    void onShaderProgramProperty(CMFCPropertyGridProperty* pgp);

    // -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -
    // Stuff related to the "shader" properties list

    void createShaderPropertyList();
    void updateShaderPropertyList(const Shader& mat);

    CMFCPropertyGridProperty* m_shaderIdPGP;
    CMFCPropertyGridProperty* m_shaderCompilesPGP;

   // -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -
    // Stuff related to the "texture" properties list

    void createTexturePropertyList();
    void updateTexturePropertyList(const Texture& tex);
    
    CMFCPropertyGridProperty* m_textureIdPGP;
    CMFCPropertyGridProperty* m_textureFileNamePGP;

    void onTextureProperty(CMFCPropertyGridProperty* pgp);

   // -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -
    // Stuff related to the "texture layer" properties list

    void createTextureLayerPropertyList();
    void updateTextureLayerPropertyList(const TextureLayer& texLayer);
    void updateTexLayerTexIdField(const TextureLayer& texLayer);
    void updateTexLayerEnvModeField(const TextureLayer& texLayer);
    void updateTexLayerRgbCombiModeField(const TextureLayer& texLayer);
    void updateTexLayerAlphaCombiModeField(const TextureLayer& texLayer);
    void updateTexLayerWrapFields(const TextureLayer& texLayer);
    void updateTexLayerBorderColorField(const TextureLayer& texLayer);

    CMFCPropertyGridProperty* m_texLayerTexIdPGP;
    CMFCPropertyGridProperty* m_texLayerEnvModePGP;
    CMFCPropertyGridProperty* m_texLayerRgbCombiModePGP;
    CMFCPropertyGridProperty* m_texLayerAlphaCombiModePGP;
    CMFCPropertyGridProperty* m_texLayerSWrapModePGP;
    CMFCPropertyGridProperty* m_texLayerTWrapModePGP;
    CMFCPropertyGridColorProperty* m_texLayerBorderColorPGP;
    //CMFCPropertyGridProperty* m_textureFileNamePGP;

    void onTextureLayerProperty(CMFCPropertyGridProperty* pgp);

    // -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -
    // Stuff related to the "uniform var" properties list

    void createUniformVarPropertyList();
    void updateUniformVarPropertyList(const UniformVar& uniVar);
    
    CMFCPropertyGridProperty* m_uniVarTypePGP;
    CMFCPropertyGridProperty* m_uniVarFloatsGroupPGP;    
    enum { MaxUniformVarFloats = 16 };
    CMFCPropertyGridProperty* m_uniVarFloatPGP[MaxUniformVarFloats];

    //CMFCPropertyGridProperty* m_textureFileNamePGP;

    void onUniformVarProperty(CMFCPropertyGridProperty* pgp);

    // -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -
    // Stuff related to the "nothing" properties list
    
    void createNothingPropertyList();

    // -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -

public:
    void SetVSDotNetLook(BOOL bSet)
    {
        for(int i = 0; i < PropertyTypes::COUNT; ++i)
        {
            m_wndPropList[i].SetVSDotNetLook(bSet);
            m_wndPropList[i].SetGroupNameFullWidth(bSet);
        }
    }

protected:
    afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
    afx_msg void OnSize(UINT nType, int cx, int cy);
    afx_msg void OnExpandAllProperties();
    afx_msg void OnUpdateExpandAllProperties(CCmdUI* pCmdUI);
    afx_msg void OnSortProperties();
    afx_msg void OnUpdateSortProperties(CCmdUI* pCmdUI);
    afx_msg void OnSetFocus(CWnd* pOldWnd);
    afx_msg void OnSettingChange(UINT uFlags, LPCTSTR lpszSection);
    afx_msg LRESULT OnPropertyChanged(WPARAM wparam, LPARAM lparam);
    afx_msg LRESULT OnUpdateActivePropertyList(WPARAM, LPARAM);
    DECLARE_MESSAGE_MAP()

    void InitPropList();
    void SetPropListFont();
public:
protected:
};

